;
(function ($, window) {
    'use strict';

    var imageEdit = window.imageEdit = {
        hold: {},
        iasapi: {},
        fileId: '',
        _view: false,
        $imagePanel: null,

        intval: function (f) {
            return f || 0;
        },

        setDisabled: function (el, s) {
            if (s) {
                el.removeClass('disabled');
                $('input', el).removeAttr('disabled');
            } else {
                el.addClass('disabled');
                $('input', el).prop('disabled', true);
            }
        },

        init: function (fileId) {
            var t = this,
                old = $('#image-editor-' + t.fileId),
                x = t.intval($('#imgedit-x-' + fileId).val()),
                y = t.intval($('#imgedit-y-' + fileId).val());

            if (t.fileId !== fileId && old.length) {
                t.close();
            }

            this.$imagePanel = $('#imgedit-panel-' + fileId);

            t.hold.w = t.hold.ow = x;
            t.hold.h = t.hold.oh = y;
            t.hold.xy_ratio = x / y;
            t.hold.sizer = parseFloat($('#imgedit-sizer-' + fileId).val());
            t.fileId = fileId;

            $('#imgedit-response-' + fileId).empty();

            this.initEvents();
        },

        initEvents: function () {
            this.$imagePanel.on('keypress.ycmf-image-edit', 'input[type="text"]', function (e) {
                var k = e.keyCode;

                if (36 < k && k < 41) {
                    $(this).blur();
                }

                if (13 === k) {
                    e.preventDefault();
                    e.stopPropagation();
                    return false;
                }
            });

            this.$imagePanel.on('click.ycmf-image-edit', '.imgedit-help-toggle', function () {
                return imageEdit.toggleHelp(this);
            });

            this.$imagePanel.on('click.ycmf-image-edit', '.imgedit-close', function () {
                return imageEdit.close(true);
            });

            this.$imagePanel.on('keyup.ycmf-image-edit, blur.ycmf-image-edit', '#imgedit-scale-width-' + this.fileId, function () {
                imageEdit.scaleChanged(1);
            });

            this.$imagePanel.on('keyup.ycmf-image-edit, blur.ycmf-image-edit', '#imgedit-scale-height-' + this.fileId, function () {
                imageEdit.scaleChanged(0);
            });

            this.$imagePanel.on('keyup.ycmf-image-edit, blur.ycmf-image-edit', '#imgedit-crop-width-' + this.fileId, function () {
                imageEdit.setRatioSelection(0, this);
            });

            this.$imagePanel.on('keyup.ycmf-image-edit, blur.ycmf-image-edit', '#imgedit-crop-height-' + this.fileId, function () {
                imageEdit.setRatioSelection(1, this);
            });

            this.$imagePanel.on('keyup.ycmf-image-edit, blur.ycmf-image-edit',
                '#imgedit-sel-width-' + this.fileId + ', #imgedit-sel-height-' + this.fileId, function () {
                    imageEdit.setNumSelection();
                });

            this.$imagePanel.on('click.ycmf-image-edit', '.imgedit-crop', function () {
                imageEdit.crop(this);
                return false;
            });

            this.$imagePanel.on('click.ycmf-image-edit', '.imgedit-rleft', function () {
                imageEdit.rotate(90, this);
                return false;
            });

            this.$imagePanel.on('click.ycmf-image-edit', '.imgedit-rright', function () {
                imageEdit.rotate(-90, this);
                return false;
            });

            this.$imagePanel.on('click.ycmf-image-edit', '.imgedit-flipv', function () {
                imageEdit.flip(1, this);
                return false;
            });

            this.$imagePanel.on('click.ycmf-image-edit', '.imgedit-fliph', function () {
                imageEdit.flip(2, this);
                return false;
            });

            this.$imagePanel.on('click.ycmf-image-edit', '.imgedit-undo', function () {
                imageEdit.undo();
                return false;
            });

            this.$imagePanel.on('click.ycmf-image-edit', '.imgedit-redo', function () {
                imageEdit.redo();
                return false;
            });

            this.$imagePanel.on('click.ycmf-image-edit', '.imgedit-scale-btn', function () {
                imageEdit.action('scale');
                return false;
            });

            this.$imagePanel.on('click.ycmf-image-edit', '.imgedit-restore-btn', function () {
                imageEdit.action('restore');
                return false;
            });

            this.$imagePanel.on('click.ycmf-image-edit', '.imgedit-submit-btn', function () {
                imageEdit.save();
                return false;
            });

            /*
             this.$imagePanel.on('load.ycmf-image-edit', '#image-preview-' + this.fileId, function () {
             imageEdit.imgLoaded();
             });
             */
        },

        imgLoaded: function () {
            var img = $('#image-preview-' + this.fileId),
                parent = $('#imgedit-crop-' + this.fileId);
            this.initCrop(img, parent);
            this.setCropSelection(0);
            this.toggleEditor(0);
        },

        initCrop: function (image, parent) {
            var t = this,
                fileId = this.fileId,
                selW = $('#imgedit-sel-width-' + fileId),
                selH = $('#imgedit-sel-height-' + fileId),
                $img;

            t.iasapi = $(image).imgAreaSelect({
                parent: parent,
                instance: true,
                handles: true,
                keys: true,
                minWidth: 3,
                minHeight: 3,

                onInit: function (img) {
                    // Ensure that the imgareaselect wrapper elements are position:absolute
                    // (even if we're in a position:fixed modal)
                    $img = $(img);
                    $img.next().css('position', 'absolute')
                        .nextAll('.imgareaselect-outer').css('position', 'absolute');

                    parent.children().mousedown(function (e) {
                        var ratio = false, sel, defRatio;

                        if (e.shiftKey) {
                            sel = t.iasapi.getSelection();
                            defRatio = t.getSelRatio();
                            ratio = ( sel && sel.width && sel.height ) ? sel.width + ':' + sel.height : defRatio;
                        }

                        t.iasapi.setOptions({
                            aspectRatio: ratio
                        });
                    });
                },

                onSelectStart: function () {
                    imageEdit.setDisabled($('#imgedit-crop-sel-' + fileId), 1);
                },

                onSelectEnd: function (img, c) {
                    imageEdit.setCropSelection(c);
                },

                onSelectChange: function (img, c) {
                    var sizer = imageEdit.hold.sizer;
                    selW.val(imageEdit.round(c.width / sizer));
                    selH.val(imageEdit.round(c.height / sizer));
                }
            });
        },

        addStep: function (op) {
            var t = this,
                fileId = this.fileId,
                elem = $('#imgedit-history-' + fileId),
                history = ( elem.val() !== '' ) ? JSON.parse(elem.val()) : [],
                undone = $('#imgedit-undone-' + fileId),
                pop = t.intval(undone.val());

            while (pop > 0) {
                history.pop();
                pop--;
            }
            undone.val(0); // reset

            history.push(op);
            elem.val(JSON.stringify(history));

            t.refreshEditor(function () {
                t.setDisabled($('#image-undo-' + fileId), true);
                t.setDisabled($('#image-redo-' + fileId), false);
            });
        },

        rotate: function (angle, t) {
            if ($(t).hasClass('disabled')) {
                return false;
            }

            this.addStep({ 'r': { 'r': angle, 'fw': this.hold.h, 'fh': this.hold.w }});
        },

        flip: function (axis, t) {
            if ($(t).hasClass('disabled')) {
                return false;
            }

            this.addStep({ 'f': { 'f': axis, 'fw': this.hold.w, 'fh': this.hold.h }});
        },

        crop: function (t) {
            var fileId = this.fileId,
                sel = $('#imgedit-selection-' + fileId).val(),
                w = this.intval($('#imgedit-sel-width-' + fileId).val()),
                h = this.intval($('#imgedit-sel-height-' + fileId).val());

            if ($(t).hasClass('disabled') || sel === '') {
                return false;
            }

            sel = JSON.parse(sel);
            if (sel.w > 0 && sel.h > 0 && w > 0 && h > 0) {
                sel.fw = w;
                sel.fh = h;
                this.addStep({ 'c': sel });
            }
        },

        undo: function () {
            var t = this,
                fileId = this.fileId,
                button = $('#image-undo-' + fileId),
                elem = $('#imgedit-undone-' + fileId),
                pop = t.intval(elem.val()) + 1;

            if (button.hasClass('disabled')) {
                return;
            }

            elem.val(pop);
            t.refreshEditor(function () {
                var elem = $('#imgedit-history-' + fileId),
                    history = ( elem.val() !== '' ) ? JSON.parse(elem.val()) : [];

                t.setDisabled($('#image-redo-' + fileId), true);
                t.setDisabled(button, pop < history.length);
            });
        },

        redo: function () {
            var t = this,
                fileId = this.fileId,
                button = $('#image-redo-' + fileId), elem = $('#imgedit-undone-' + fileId),
                pop = t.intval(elem.val()) - 1;

            if (button.hasClass('disabled')) {
                return;
            }

            elem.val(pop);
            t.refreshEditor(function () {
                t.setDisabled($('#image-undo-' + fileId), true);
                t.setDisabled(button, pop > 0);
            });
        },

        filterHistory: function (setSize) {
            // apply undo state to history
            var history = $('#imgedit-history-' + this.fileId).val(), pop, n, o, i, op = [];

            if (history !== '') {
                history = JSON.parse(history);
                pop = this.intval($('#imgedit-undone-' + this.fileId).val());
                if (pop > 0) {
                    while (pop > 0) {
                        history.pop();
                        pop--;
                    }
                }

                if (setSize) {
                    if (!history.length) {
                        this.hold.w = this.hold.ow;
                        this.hold.h = this.hold.oh;
                        return '';
                    }

                    // restore
                    o = history[history.length - 1];
                    o = o.c || o.r || o.f || false;

                    if (o) {
                        this.hold.w = o.fw;
                        this.hold.h = o.fh;
                    }
                }

                // filter the values
                for (n in history) {
                    i = history[n];
                    if (i.hasOwnProperty('c')) {
                        op[n] = { 'c': { 'x': i.c.x, 'y': i.c.y, 'w': i.c.w, 'h': i.c.h } };
                    } else if (i.hasOwnProperty('r')) {
                        op[n] = { 'r': i.r.r };
                    } else if (i.hasOwnProperty('f')) {
                        op[n] = { 'f': i.f.f };
                    }
                }
                return JSON.stringify(op);
            }
            return '';
        },

        refreshEditor: function (callback) {
            var t = this, data, img, fileId = this.fileId;

            t.toggleEditor(1);
            data = {
                'id': fileId,
                'history': t.filterHistory(1),
                'rand': t.intval(Math.random() * 1000000)
            };

            img = $('<img id="image-preview-' + fileId + '" />')
                .on('load', function () {
                    var max1, max2, parent = $('#imgedit-crop-' + fileId), t = imageEdit;

                    parent.empty().append(img);

                    // w, h are the new full size dims
                    max1 = Math.max(t.hold.w, t.hold.h);
                    max2 = Math.max($(img).width(), $(img).height());
                    t.hold.sizer = max1 > max2 ? max2 / max1 : 1;

                    t.initCrop(img, parent);
                    t.setCropSelection(0);

                    if ((typeof callback !== 'undefined') && callback !== null) {
                        callback();
                    }

                    if ($('#imgedit-history-' + fileId).val() && $('#imgedit-undone-' + fileId).val() === '0') {
                        $('input.imgedit-submit-btn', this.$imagePanel).removeAttr('disabled');
                    } else {
                        $('input.imgedit-submit-btn', this.$imagePanel).prop('disabled', true);
                    }

                    t.toggleEditor(0);
                })
                .on('error', function () {
                    $('#imgedit-crop-' + fileId).empty().append('<div class="error"><p>图片预览出错</p></div>');
                    t.toggleEditor(0);
                })
                .attr('src', 'index.php?r=file/imgedit-preview' + '&' + $.param(data));
        },

        action: function (action) {
            var t = this, data = {}, w, h, fw, fh, fileId = this.fileId;

            if (t.notSaved()) {
                return false;
            }

            data[yii.getCsrfParam()] = yii.getCsrfToken();

            if ('scale' === action) {
                w = $('#imgedit-scale-width-' + fileId),
                    h = $('#imgedit-scale-height-' + fileId),
                    fw = t.intval(w.val()),
                    fh = t.intval(h.val());

                if (fw < 1) {
                    w.focus();
                    return false;
                } else if (fh < 1) {
                    h.focus();
                    return false;
                }

                if (fw === t.hold.ow || fh === t.hold.oh) {
                    return false;
                }

                data['do'] = 'scale';
                data.fwidth = fw;
                data.fheight = fh;
            } else if ('restore' === action) {
                data['do'] = 'restore';
            } else {
                return false;
            }

            t.toggleEditor(1);
            $.post('index.php?r=file/image-editor&id=' + fileId, data, function (r) {
                t.$imagePanel.off('.ycmf-image-edit');
                $('#image-editor-' + fileId).empty().append(r);
                t.toggleEditor(0);
                // refresh the attachment model so that changes propagate
                if (t._view) {
                    t._view.refresh();
                }
            });
        },

        save: function () {
            var data,
                fileId = this.fileId,
                target = this.getTarget(),
                history = this.filterHistory(0),
                self = this;

            if ('' === history) {
                return false;
            }

            this.toggleEditor(1);
            data = {
                'history': history,
                'target': target,
                'context': $('#image-edit-context').length ? $('#image-edit-context').val() : null,
                'do': 'save'
            };

            data[yii.getCsrfParam()] = yii.getCsrfToken();

            $.post('index.php?r=file/image-editor&id=' + fileId, data, function (r) {
                var ret;

                if ($.isPlainObject(r)) {
                    ret = r;
                } else {
                    ret = JSON.parse(r);
                }

                if (ret.error) {
                    $('#imgedit-response-' + fileId).html('<div class="alert alert-danger"><p>' + ret.error + '</p><div>');
                    imageEdit.close();
                    return;
                }

                if (ret.fw && ret.fh) {
                    $('#media-dims-' + fileId).html(ret.fw + ' &times; ' + ret.fh);
                }

                if (ret.thumbnail) {
                    $('.thumbnail img', '#image-head-' + fileId).attr('src', '' + ret.thumbnail);
                }

                if (ret.msg) {
                    $('#imgedit-response-' + fileId).html('<div class="alert alert-success"><p>' + ret.msg + '</p></div>');
                }

                if (self._view) {
                    self._view.save();
                } else {
                    imageEdit.close();
                }
            });
        },

        open: function (view) {
            this._view = view;

            var data, fileId = this.fileId, elem = $('#image-editor-' + fileId), head = $('#media-head-' + fileId),
                btn = $('#imgedit-open-btn-' + fileId), spin = btn.siblings('.spinner');

            btn.prop('disabled', true);
            spin.show();

            elem.load('index.php?r=file/image-editor&id=' + fileId, function () {
                elem.fadeIn('fast');
                head.fadeOut('fast', function () {
                    btn.removeAttr('disabled');
                    spin.hide();
                });
            });
        },

        round: function (num) {
            var s;
            num = Math.round(num);

            if (this.hold.sizer > 0.6) {
                return num;
            }

            s = num.toString().slice(-1);

            if ('1' === s) {
                return num - 1;
            } else if ('9' === s) {
                return num + 1;
            }

            return num;
        },

        setCropSelection: function (c) {
            var sel,
                fileId = this.fileId,
                min = $('#imgedit-minthumb-' + fileId).val() || '128:128',
                sizer = this.hold.sizer;
            min = min.split(':');
            c = c || 0;

            if (!c || ( c.width < 3 && c.height < 3 )) {
                this.setDisabled($('.imgedit-crop', this.$imagePanel), 0);
                this.setDisabled($('#imgedit-crop-sel-' + fileId), 0);
                $('#imgedit-sel-width-' + fileId).val('');
                $('#imgedit-sel-height-' + fileId).val('');
                $('#imgedit-selection-' + fileId).val('');
                return false;
            }

            if (c.width < (min[0] * sizer) && c.height < (min[1] * sizer)) {
                this.setDisabled($('.imgedit-crop', this.$imagePanel), 0);
                $('#imgedit-selection-' + fileId).val('');
                return false;
            }

            sel = { 'x': c.x1, 'y': c.y1, 'w': c.width, 'h': c.height };
            this.setDisabled($('.imgedit-crop', '#imgedit-panel-' + fileId), 1);
            $('#imgedit-selection-' + fileId).val(JSON.stringify(sel));
        },

        setRatioSelection: function (n, el) {
            var sel, r,
                fileId = this.fileId,
                x = this.intval($('#imgedit-crop-width-' + fileId).val()),
                y = this.intval($('#imgedit-crop-height-' + fileId).val()),
                h = $('#image-preview-' + fileId).height();

            if (!this.intval($(el).val())) {
                $(el).val('');
                return;
            }

            if (x && y) {
                console.log(x, y);
                this.iasapi.setOptions({
                    aspectRatio: x + ':' + y
                });

                if (sel = this.iasapi.getSelection(true)) {
                    r = Math.ceil(sel.y1 + ( ( sel.x2 - sel.x1 ) / ( x / y ) ));

                    if (r > h) {
                        r = h;
                        if (n) {
                            $('#imgedit-crop-height-' + fileId).val('');
                        } else {
                            $('#imgedit-crop-width-' + fileId).val('');
                        }
                    }

                    this.iasapi.setSelection(sel.x1, sel.y1, sel.x2, r);
                    this.iasapi.update();
                }
            }
        },

        setNumSelection: function () {
            var fileId = this.fileId,
                sel, elX = $('#imgedit-sel-width-' + fileId), elY = $('#imgedit-sel-height-' + fileId),
                x = this.intval(elX.val()), y = this.intval(elY.val()),
                img = $('#image-preview-' + fileId), imgh = img.height(), imgw = img.width(),
                sizer = this.hold.sizer, x1, y1, x2, y2, ias = this.iasapi;

            if (x < 1) {
                elX.val('');
                return false;
            }

            if (y < 1) {
                elY.val('');
                return false;
            }

            if (x && y && ( sel = ias.getSelection() )) {
                x2 = sel.x1 + Math.round(x * sizer);
                y2 = sel.y1 + Math.round(y * sizer);
                x1 = sel.x1;
                y1 = sel.y1;

                if (x2 > imgw) {
                    x1 = 0;
                    x2 = imgw;
                    elX.val(Math.round(x2 / sizer));
                }

                if (y2 > imgh) {
                    y1 = 0;
                    y2 = imgh;
                    elY.val(Math.round(y2 / sizer));
                }

                ias.setSelection(x1, y1, x2, y2);
                ias.update();
                this.setCropSelection(ias.getSelection());
            }
        },

        notSaved: function () {
            var h = $('#imgedit-history-' + this.fileId).val(),
                history = ( h !== '' ) ? JSON.parse(h) : [],
                pop = this.intval($('#imgedit-undone-' + this.fileId).val());

            if (pop < history.length) {
                if (confirm($('#imgedit-leaving-' + this.fileId).html())) {
                    return false;
                }
                return true;
            }
            return false;
        },

        close: function (warn) {
            var fileId = this.fileId;

            warn = warn || false;

            if (warn && this.notSaved()) {
                return false;
            }

            this.fileId = '';
            this.hold = {};
            this.iasapi = {};

            // If we've loaded the editor in the context of a Media Modal, then switch to the previous view,
            // whatever that might have been.
            if (this._view) {
                this._view.back();
            }
            // In case we are not accessing the image editor in the context of a View, close the editor the old-skool way
            else {
                $('#image-editor-' + fileId).fadeOut('fast', function () {
                    $('#image-head-' + fileId).fadeIn('fast');
                    $(this).empty();
                });
            }

            this.$imagePanel.off('.ycmf-image-edit');
            this.$imagePanel = null;
            return true;
        },

        scaleChanged: function (x) {
            var w = $('#imgedit-scale-width-' + this.fileId),
                h = $('#imgedit-scale-height-' + this.fileId),
                warn = $('#imgedit-scale-warn-' + this.fileId),
                w1 = '',
                h1 = '';

            if (x) {
                h1 = ( w.val() !== '' ) ? Math.round(w.val() / this.hold.xy_ratio) : '';
                h.val(h1);
            } else {
                w1 = ( h.val() !== '' ) ? Math.round(h.val() * this.hold.xy_ratio) : '';
                w.val(w1);
            }

            if (( h1 && h1 > this.hold.oh ) || ( w1 && w1 > this.hold.ow )) {
                warn.css('visibility', 'visible');
            } else {
                warn.css('visibility', 'hidden');
            }
        },

        getSelRatio: function () {
            var x = this.hold.w, y = this.hold.h,
                X = this.intval($('#imgedit-crop-width-' + this.fileId).val()),
                Y = this.intval($('#imgedit-crop-height-' + this.fileId).val());

            if (X && Y) {
                return X + ':' + Y;
            }

            if (x && y) {
                return x + ':' + y;
            }

            return '1:1';
        },

        getTarget: function () {
            return $('input[name="imgedit-target-' + this.fileId + '"]:checked', '#imgedit-save-target-' + this.fileId).val() || 'full';
        },

        toggleEditor: function (toggle) {
            var wait = $('#imgedit-wait-' + this.fileId);

            if (toggle) {
                wait.height(this.$imagePanel.height()).fadeIn('fast');
            } else {
                wait.fadeOut('fast');
            }
        },

        toggleHelp: function (el) {
            $(el).parents('.imgedit-group')
                .toggleClass('imgedit-help-toggled')
                .find('.imgedit-help')
                .slideToggle('fast');
            return false;
        }
    };
})(jQuery, window);